﻿using HarfBuzzSharp;
using LightCAD.Core;
using LightCAD.Core.Elements;
using LightCAD.Runtime;
using LightCAD.Three;
using netDxf.Entities;
using SkiaSharp;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Linq;
using LightCAD.MathLib;
using Avalonia.Controls;
using static LightCAD.Drawing.Actions.StretchAction;
using netDxf.Collections;

namespace LightCAD.Drawing.Actions
{
    public class StretchAction : ElementAction
    {

        public static string CommandName;
        public static LcCreateMethod[] CreateMethods;
        private Dictionary<LcElement, List<Grip>> Lcgrips = new Dictionary<LcElement, List<Grip>>();

        private  List<LcElement> lcElements = new List<LcElement>();
        public class Grip 
        {
            public string Name { get; set; }
            public Vector2 Position { get; set; }
        
        }


        static StretchAction()
        {
            CommandName = "STRETCH";
            CreateMethods = new LcCreateMethod[1];
            CreateMethods[0] = new LcCreateMethod()
            {
                Name = "STR",
                Description = "STRETCH",
                Steps = new LcCreateStep[]
                {
                    new LcCreateStep{ Name="Step0", Options="STRETCH 选择元素:" },
                    new LcCreateStep{ Name="Step1", Options="STRETCH 指定基点:" },
                    new LcCreateStep{ Name="Step2", Options="STRETCH 指定第二个点(使用第一个点作为位移):" },
                }
            };
            
        }

        internal static void Initilize()
        {
            ElementActions.Stretch = new StretchAction();
           
            //LcDocument.ElementActions.Add(BuiltinElementType.DimDiametric, ElementActions.Stretch);
        }

        private PointInputer inputer { get; set; }

        private Vector2 startpoint;
        private Vector2 endpoint;
        private List<LcElement> selElement;
        private Box2 selectBox;



        public StretchAction()
        {

        }
        public StretchAction(IDocumentEditor docEditor) : base(docEditor)
        {
        
            this.commandCtrl.WriteInfo("命令 ：STR");
        }
        private LcCreateMethod GetMethod(string method)
        {
            if (method == null) return CreateMethods[0];
            var getted= CreateMethods.FirstOrDefault((m) => m.Name == method);
            if (getted == null)
                return CreateMethods[0];
            else
                return getted;
        }
        public async void ExecCreate(string[] args = null)
        {
            
            this.StartCreating();
            //this.Segments = new List<RolineSegment>();
            var curMethod = SetCurMethod(CreateMethods, 0);
            var ElementInputer = new ElementInputer(this.docEditor);
            this.inputer = new PointInputer(this.docEditor);
            var se = new ElementSetInputer(this.docEditor);
           
            Step0:
            var step0 = curMethod.Steps[0];
            //this.vportRt.SetStatus(ViewportStatus.RectSelect, true);
            //LcElement element=  this.docEditor;
            var result0 = await se.Execute(step0.Options);
            if (se.isCancelled) { this.Cancel(); return; }
           
            // zcb: 增加Res0为空的判定
            if (result0 == null)
            {
                this.Cancel();
                goto End;
            }
            if (result0.ValueX == null)
            {
                
                goto Step0;
            }
            else
            {

                //List<LcElement> ss = this.docRt.Action.SelectedElements;
                selElement = result0.ValueX as List<LcElement>;
                if (selElement.Count > 0)
                {
                    //记录框选box
                    var fp = this.vportRt.ConvertScrToWcs( this.vportRt.PointerPressedPosition.ToVector2d());
                    var sp = this.vportRt.ConvertScrToWcs(this.vportRt.PointerReleasedPosition.ToVector2d());
                    selectBox = new Box2().SetFromPoints(fp, sp);
                    goto Step1;
                }
                else {
                    goto Step0;
                }
            }
            Step1:
            var step1 = curMethod.Steps[1];
            var result1 = await inputer.Execute(step1.Options);
            if (inputer.isCancelled) { this.Cancel(); return; }
            // zcb: 增加Res0为空的判定
            if (result1 == null)
            {
                this.Cancel();
                goto End;
            }
            if (result1.ValueX == null)
            {
                if (result1.Option != null)
                {
                }
                else
                {
                    goto Step2;
                }
            }
            else
            {
                this.startpoint = (Vector2)result1.ValueX;
                CreateDimElement();
                goto Step2;
            }
            Step2:
            var step2 = curMethod.Steps[2];
            var result2 = await inputer.Execute(step2.Options);
            if (inputer.isCancelled) { this.Cancel(); return; }
            // zcb: 增加Res0为空的判定
            if (result2 == null)
            {
                this.Cancel();
                goto End;
            }
            if (result2.ValueX == null)
            {
                if (result2.Option != null)
                {

                }
                else
                {
                    goto End;
                }
            }
            else
            {
                this.endpoint = (Vector2)result2.ValueX;
                DelElement();
               
                goto End;
            }

            End:
            this.EndCreating();

        }
        private void CreateDimElement()
        {

            //判断选中元素的夹点 是否在box中
            //夹点集合()
            var grips = new List<ControlGrip>();
            for (int i = 0; i <selElement.Count; i++)
            {
                List<Grip> grips1 = new List<Grip>();
                var lcElement = selElement[i] as LcElement;
                var eleAction = (lcElement.RtAction as ElementAction);
                grips=eleAction.SetViewport(this.vportRt).GetControlGrips(lcElement).ToList();

                //特殊情况  圆弧中点

                Grip arcgrip = new Grip();

                //去除不在box中的 夹点
                for (int j = grips.Count-1; j >=0; j--)
                {
                    if (lcElement is LcArc) {
                        if (grips[j].Name == "ArcMidp") {

                            arcgrip.Name = grips[j].Name;
                            arcgrip.Position = grips[j].Position.Clone();
                        }
                    
                    }

                    if (!grips[j].IntersectWithBox(selectBox))
                    {
                        grips.Remove(grips[j]);
                    }
                    else 
                    {
                            Grip grip = new Grip();
                            grip.Name = grips[j].Name;
                            grip.Position = grips[j].Position.Clone();
                            grips1.Add(grip);
                        
                    }
                }
                //如果是圆弧 需要将中点也加进去
                if (lcElement is LcArc) 
                {

                    if (grips1.Where(n => n.Name == "ArcMidp").Count() > 0)
                    {

                    }
                    else 
                    {
                        //将中点加入集合
                        grips1.Add(arcgrip);
                    }


                }

                if (grips1.Count > 0) 
                {
                    
                    Lcgrips.Add(lcElement.Clone(), grips1);
                    lcElements.Add(lcElement);
                }
                

            }

        }

        private void DelElement() 
        {
            if (this.endpoint != null)
            {
                var doc = this.docRt.Document;
                List<LcElement> dickeys = new List<LcElement>(Lcgrips.Keys);

                for (int i = 0; i < lcElements.Count; i++)
                {
                    doc.ModelSpace.RemoveElement(lcElements[i]);
                }
                //表示拉伸完结  需要重新draw
                for (int i = 0; i < dickeys.Count; i++)
                {
                    //需要判断所有的element是什么类型
                    if (dickeys[i] is LcLine)
                    {
                        var lcline = doc.CreateObject<LcLine>();
                        lcline = dickeys[i] as LcLine;
                        doc.ModelSpace.InsertElement(lcline);

                    }
                    if (dickeys[i] is LcArc)
                    {
                        var lcArc = doc.CreateObject<LcArc>();
                        lcArc = dickeys[i] as LcArc;
                        doc.ModelSpace.InsertElement(lcArc);

                    }
                }

            }

        }

        /// <summary>
        /// 选中的对象
        /// </summary>
        /// <param name="elements"></param>
        /// <returns></returns>
        private bool CreateSelects(LcElement elements)
        {

         
                if (elements is LcCircle|| elements is LcArc) {
                    return true;

                }
               
            return false;

        }


        public override void Cancel()
        {
            base.Cancel();
            this.vportRt.SetCreateDrawer(null);
        }
       
        

        public override void CreateElement(LcElement element, Matrix3 matrix)
        {
        }
        public override void CreateElement(LcElement element,Vector2 basePoint, double scaleFactor)
        {
          
        }
        public override void CreateElement(LcElement element, Vector2 basePoint, Vector2 scaleVector)
        {

        }
        public override void Draw(SKCanvas canvas, LcElement element, Matrix3 matrix)
        {

        }
     


        public override void DrawAuxLines(SKCanvas canvas)
        {
            if (this.startpoint != null&&this.endpoint==null) 
            {
                var mp = this.vportRt.PointerMovedPosition.ToVector2d();
                var wcs_mp = this.vportRt.ConvertScrToWcs(mp);
                DrawAuxLine(canvas, this.startpoint, wcs_mp);

            }

         

        }

        private void DrawAuxLine(SKCanvas canvas, Vector2 p0, Vector2 p1)
        {
            var sk_pre = this.vportRt.ConvertWcsToScr(p0).ToSKPoint();
            var sk_p = this.vportRt.ConvertWcsToScr(p1).ToSKPoint();
            //辅助元素的颜色 
            //辅助曲线的颜色，包括辅助长度，辅助角度等
            canvas.DrawLine(sk_pre, sk_p, new SKPaint { Color = this.vportRt.GetAuxColorValue(), IsStroke = true });

            if (!(p0.X == p1.X && p0.Y == p1.Y)) 
            {
                //移动鼠标需要计算
                //计算鼠标移动距离 向量等；
                double dis = (p1 - p0).Length();
                Vector2 xlpoint=  new Vector2(p1.X - p0.X, p1.Y - p0.Y);

                //字典中的所有夹点都需要 移动相同距离
                List<LcElement> dickeys = new List<LcElement>(Lcgrips.Keys);
                for (int i = 0; i < Lcgrips.Count; i++)
                {
                    for (int j = 0; j < Lcgrips[dickeys[i]].Count; j++)
                    {
                        //改变夹点 新的点位
                        Vector2 posxy = new Vector2();
                        Vector2 newposxy = new Vector2();
                        posxy.X = Lcgrips[dickeys[i]][j].Position.Clone().X;
                        posxy.Y = Lcgrips[dickeys[i]][j].Position.Clone().Y;

                        newposxy = posxy + (new Vector2(xlpoint.X * dis, xlpoint.Y * dis)) / Math.Sqrt(Math.Abs((Math.Pow(xlpoint.X, 2.0) + Math.Pow(xlpoint.Y, 2.0))));
                        //不直接赋值 
                        //直线
                        if (dickeys[i] is LcLine)
                        {
                            var lcline = dickeys[i] as LcLine;
                            if (Lcgrips[dickeys[i]][j].Name == "Start")
                            {
                                lcline.Start = newposxy;

                            }
                            else if (Lcgrips[dickeys[i]][j].Name == "End")
                            {
                                lcline.End = newposxy;
                            }

                        }
                        //圆弧
                        if (dickeys[i] is LcArc)
                        {
                            //圆弧的中点也需要 变化
                            var lcarc = dickeys[i] as LcArc;
                            if (Lcgrips[dickeys[i]][j].Name == "Start")
                            {
                                lcarc.Startp = newposxy;
                                //lcarc.Midp=

                            }
                            else if (Lcgrips[dickeys[i]][j].Name == "End")
                            {
                                lcarc.Endp = newposxy;
                            }
                            if (Lcgrips[dickeys[i]][j].Name == "ArcMidp")
                            {
                                //中点是肯定会变的 所以 mid点一定要加入集合
                                lcarc.Midp = newposxy;

                            }
                            //圆弧需要使用三点画弧法
                            //var eleAction = (lcarc.RtAction as ArcAction);
                            //Arc2d arc2D= ArcAction.CreateArc3P(lcarc.Startp, lcarc.Midp,lcarc.Endp,out bool reverse);
                            // Matrix3 matrix = Matrix3.GetTranslate(new Vector2(0, 0));
                            // this.vportRt.DrawArc(arc2D, matrix, canvas, Constants.auxElementPen);

                        }
                    }

                    if (dickeys[i] is LcLine)
                    {
                        var lcline = dickeys[i] as LcLine;
                        var start = this.vportRt.ConvertWcsToScr(lcline.Start).ToSKPoint();
                        var end = this.vportRt.ConvertWcsToScr(lcline.End).ToSKPoint();
                        canvas.DrawLine(start, end, Constants.draggingPen);

                    }
                    //圆弧
                    if (dickeys[i] is LcArc)
                    {
                        //圆弧的中点也需要 变化
                        var lcarc = dickeys[i] as LcArc;
                        //圆弧需要使用三点画弧法
                        //var eleAction = (lcarc.RtAction as ArcAction);
                        Arc2d arc2D = ArcAction.CreateArc3P(lcarc.Startp, lcarc.Midp, lcarc.Endp, out bool reverse);
                        //起点终点需要转换
                        if (reverse) 
                        {
                            var st = arc2D.StartAngle;
                            arc2D.StartAngle = arc2D.EndAngle;
                            arc2D.EndAngle = st;


                        }
                        Matrix3 matrix = Matrix3.GetTranslate(new Vector2(0, 0));
                        this.vportRt.DrawArc(arc2D, matrix, canvas, new SKPaint { Color = this.vportRt.GetAuxColorValue(), IsStroke = true });

                    }
                }


            }



        }
        #region Grip
        public override ControlGrip[] GetControlGrips(LcElement element)
        {

            var grips = new List<ControlGrip>();
            return grips.ToArray();
        }
 


     


        public override void SetDragGrip(LcElement element, string gripName, Vector2 position, bool isEnd)
        {
            
        }


        public override void DrawDragGrip(SKCanvas canvas)
        {

        }

        #endregion
        public static double distance(Vector2 p1, Vector2 p2)
        {
            double result = 0;
            result = Math.Sqrt((p1.X - p2.X) * (p1.X - p2.X) + (p1.Y - p2.Y) * (p1.Y - p2.Y));
            return result;

        }
        public override List<PropertyObserver> GetPropertyObservers()
        {
            return new List<PropertyObserver>();
            
        }
    }
}
